#include "tcpserver.h"

void writeMsg(QTcpSocket *tcpSocket, const Message &msg){
    tcpSocket->write(msg.toByteArray());
    auto f = tcpSocket->flush();
    qDebug() << "writeMsg tcpSocket->flush:" << f;
}


// void TcpServer::doOneTask(QTcpSocket *tcpSocket, const Message &msg)
// {
//     tcpSocket->write(msg.toByteArray());
//     auto f = tcpSocket->flush();
//     qDebug() << "tcpSocket->flush:" << f;
// }

TcpServer::TcpServer(QObject *parent, int port)
    : QTcpServer{parent}
{
    listen(QHostAddress::Any, port);
    // connect(this, &TcpServer::doBroadCast, this, &TcpServer::broadcast, Qt::DirectConnection);
}

const QHash<QString, TcpClientSocket *> &TcpServer::getClientSocketMap()
{
    return clientSocketMap;
}

void TcpServer::broadcast(Message *msg)
{
    QListIterator<TcpClientSocket*> i(clientSocketMap.values());

    for(; i.hasNext();){
        MessageTask* task = new MessageTask(i.next(), msg);
        QThreadPool::globalInstance()->start(task);
    }

}

void TcpServer::clientDataReady(Message *msg, TcpClientSocket * clientSocket)
{
    auto userName{clientSocket->getUserName()};
    msg->setFrom(userName);

    switch (msg->getCmdType()) {
    case CmdType::Login:{
        clientSocketMap.insert(userName, clientSocket);

        // emit doBroadCast(msg);
        broadcast(msg);
        emit serverStatusChange(msg);
        break;
    }
    case CmdType::Chat:{
        auto socket = clientSocketMap.value(msg->getTo());
        socket->writeMsg(msg);
        break;
    }

    case Logout:
        break;
    }
}

void TcpServer::clientDisconected(TcpClientSocket* clientSocket)
{
    auto userName = clientSocket->getUserName();
    clientSocketMap.remove(userName);
    qDebug()<< "disconned:" << userName;
    Message *msg = new Message(CmdType::Logout, "", "", userName);
    emit serverStatusChange(msg);
    // emit doBroadCast(msg);
    broadcast(msg);
}

void TcpServer::incomingConnection(qintptr handle)
{
    qDebug() << "incomingConnection:" << handle;
    TcpClientSocket *tcpClientSocket = new TcpClientSocket(this);
    connect(tcpClientSocket, &TcpClientSocket::dataReady, this, &TcpServer::clientDataReady);
    connect(tcpClientSocket, &TcpClientSocket::disConnected, this, &TcpServer::clientDisconected);
    tcpClientSocket->setSocketDescriptor(handle);
    tcpClientSocket->socketDescriptor();
    addPendingConnection(tcpClientSocket);
    qDebug()<< "TcpServer::incomingConnection";
}


